package com.sonic.db.dao;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;

import com.sonic.db.utils.MQHibernateUtil;
import com.sonic.dto.db.MqtCategory;
import com.sonic.dto.db.MqtMobileSettings;
import com.sonic.dto.db.MqtPapCategorySettings;
import com.sonic.dto.db.MqtPapSettings;
import com.sonic.dto.db.MqtPapSubcategorySettings;
import com.sonic.dto.db.MqtSecDetailsColumnsSettings;
import com.sonic.dto.db.MqtSubcategory;
import com.sonic.dto.db.MqtTableColumns;
import com.sonic.dto.db.MqtTableColumnsSettings;
import com.sonic.dto.db.MqtTableSecurities;
import com.sonic.dto.db.MqtTableSecuritiesSettings;
import com.sonic.dto.db.MqtTableSettings;
import com.sonic.dto.db.MqtTransListColumnsSettings;
import com.sonic.dto.ws.services.settings.MQAllSettings;
import com.sonic.dto.ws.services.settings.MQAppSettings;
import com.sonic.dto.ws.services.settings.MQPAPSettings;
import com.sonic.dto.ws.services.settings.MQSavePAPSettingsRequest;
import com.sonic.dto.ws.services.settings.MQSaveSecuritySettingsRequest;
import com.sonic.dto.ws.services.settings.MQSaveSettingsResponse;
import com.sonic.dto.ws.services.settings.MQSaveTableSettingsRequest;
import com.sonic.dto.ws.services.settings.MQSettingsColumns;
import com.sonic.dto.ws.services.settings.MQSettingsRequest;
import com.sonic.dto.ws.services.settings.MQSettingsResponse;
import com.sonic.dto.ws.services.settings.MQSettingsSecurity;
import com.sonic.dto.ws.services.settings.MQTableSecDetailsSettingsDTO;
import com.sonic.dto.ws.services.settings.MQTableSettingsDTO;
import com.sonic.dto.ws.services.settings.MQTableTransListSettinngsDTO;
import com.sonic.dto.ws.services.settings.MQUserSettings;
import com.sonic.log.ejb.impl.MQLogger;

public class MQSettingsDAO {
	private static MQLogger logger = new MQLogger(MQSettingsDAO.class, "MQ-LOGIN-DAO");
	
	private Session session;
	
	private Object ownership;
	
	public MQSettingsDAO() {
		try {
			ownership = MQHibernateUtil.createSession();
			session = MQHibernateUtil.getSession();
		} catch (Exception e) {
			logger.debug("MQSettingsDAO", "Could not create database session, exception: " + e.getMessage());
		}
	}
	
	public MQSaveSettingsResponse savePAPSettings(MQSavePAPSettingsRequest request) {
		final String methodName = "savePAPSettings()";
		MQSaveSettingsResponse response = new MQSaveSettingsResponse();
		Transaction transaction = session.beginTransaction();
		transaction.begin();
		
		MqtPapSettings dbCatSettings = new MqtPapSettings();
		
		Criteria criteria = session.createCriteria(MqtMobileSettings.class)
		.add(Restrictions.eq("clientId", request.getClientID()));
		MqtMobileSettings mqtMobileSettings = (MqtMobileSettings) criteria.uniqueResult();

		criteria = session.createCriteria(MqtPapSettings.class)
		.add(Restrictions.eq("id", mqtMobileSettings.getMqtPapSettings().getId()));
		MqtPapSettings mqtPapSettings = (MqtPapSettings) criteria.uniqueResult();
		
		mqtPapSettings.setMessageCount(6);
		mqtPapSettings.setCategorySortType(0);

		Set<MqtPapCategorySettings> mqtPapCategorySettingses = new HashSet<MqtPapCategorySettings>();
		for(String catName : request.getPapSettings().getCategoryNames()) {
			
		}
		
		mqtPapSettings.setMqtPapCategorySettingses(mqtPapCategorySettingses);


		session.clear();
		transaction.commit();
		return response;
	}
	public MQSaveSettingsResponse saveTableSettings(MQSaveTableSettingsRequest request) {
		MQSaveSettingsResponse response = new MQSaveSettingsResponse();
		
		return response;
	}
	
	public MQSaveSettingsResponse saveSecuritySettings(MQSaveSecuritySettingsRequest request) {
		MQSaveSettingsResponse response = new MQSaveSettingsResponse();
		
		return response;
	}
	
	public MQSettingsResponse getSettings(MQSettingsRequest request) {
		final String methodName = "getSettings()";
		MQSettingsResponse response = new MQSettingsResponse();
		Transaction transaction = session.beginTransaction();
		transaction.begin();
		Criteria criteria = session.createCriteria(MqtMobileSettings.class)
		.add(Restrictions.eq("clientId", request.getClientID()));
		MqtMobileSettings result = (MqtMobileSettings) criteria.uniqueResult();
		if (result != null) {
			logger.debug(methodName, " --- ClientId: " + request.getClientID() + " settings has been found.");
			response.setSettingsStatusCode(0);
			response.setSettingsStatusMsg("ClientId: " + request.getClientID() + " settings has been found.");
			response.setUserSettings(translateUserSettingsToWS(result));
			response.setAllSettings(getAllSettings());
		} else {
			logger.debug(methodName, " --- ClientId: " + request.getClientID() + " settings has not been found.");
			response.setSettingsStatusCode(-1);
			response.setSettingsStatusMsg("ClientId: " + request.getClientID() + " settings has not been found.");
			response.setUserSettings(null);
		}
		session.clear();
		transaction.commit();
		return response;		
	}
	
	@SuppressWarnings("unchecked")
    private MQAllSettings getAllSettings() {
		MQAllSettings allWsSettings = new MQAllSettings();
		final String methodName = "getAllSettings()";
		
		Criteria criteria = session.createCriteria(MqtCategory.class);
		List<MqtCategory> categoryList = (List<MqtCategory>)criteria.list();
		Collections.sort(categoryList, new Comparator<MqtCategory>() {
			public int compare(MqtCategory o1, MqtCategory o2) {
				return o1.getId()-o2.getId();
            }			
		});
		
		if (categoryList != null) {
			String[] papCategoryNames = new String[categoryList.size()];
			Iterator<MqtCategory> iter = categoryList.iterator();
			int i = 0;
			while (iter.hasNext()) {
	            MqtCategory mqtCategory = (MqtCategory) iter.next();
	            papCategoryNames[i++] = mqtCategory.getName();
            }
			allWsSettings.setPapCategoryNames(papCategoryNames);
		} else {
			logger.debug(methodName, " --- Pap category columns has not been found.");
			allWsSettings.setSettingsStatusCode(-1);
			allWsSettings.setSettingsStatusMsg("Pap category columns has not been found.");
			return allWsSettings;
		}
		
		criteria = session.createCriteria(MqtSubcategory.class);
		List<MqtSubcategory> subCategoryList = (List<MqtSubcategory>)criteria.list();
		Collections.sort(subCategoryList, new Comparator<MqtSubcategory>() {
			public int compare(MqtSubcategory o1, MqtSubcategory o2) {
				return o1.getId()-o2.getId();
            }			
		});
		
		if (subCategoryList != null) {
			String[] papSubCategoryNames = new String[subCategoryList.size()];
			Iterator<MqtSubcategory> iter = subCategoryList.iterator();
			int i = 0;
			while (iter.hasNext()) {
				MqtSubcategory mqtSubCategory = (MqtSubcategory) iter.next();
				papSubCategoryNames[i++] = mqtSubCategory.getName();
            }
			allWsSettings.setPapSubcategoryNames(papSubCategoryNames);
		} else {
			logger.debug(methodName, " --- Pap subcategory columns has not been found.");
			allWsSettings.setSettingsStatusCode(-1);
			allWsSettings.setSettingsStatusMsg("Pap subcategory columns has not been found.");
			return allWsSettings;
		}
		
		criteria = session.createCriteria(MqtTableColumns.class);
		List<MqtTableColumns> tableCoulmnsList = (List<MqtTableColumns>)criteria.list();
		Collections.sort(tableCoulmnsList, new Comparator<MqtTableColumns>() {
			public int compare(MqtTableColumns o1, MqtTableColumns o2) {
				return o1.getId()-o2.getId();
            }			
		});
		
		if (tableCoulmnsList != null) {
			String[] tableColumnNames = new String[tableCoulmnsList.size()];
			String[] tableColumnShortNames = new String[tableCoulmnsList.size()];
			Iterator<MqtTableColumns> iter = tableCoulmnsList.iterator();
			int i = 0;
			while (iter.hasNext()) {
				MqtTableColumns mqtTableColumn= (MqtTableColumns) iter.next();
				tableColumnNames[i] = mqtTableColumn.getColumnName();
				tableColumnShortNames[i] = mqtTableColumn.getColumnShortname();
				i++;
            }
			allWsSettings.setTableColumnName(tableColumnNames);
			allWsSettings.setTableColumnShortName(tableColumnShortNames);
		} else {
			logger.debug(methodName, " --- Table columns has not been found.");
			allWsSettings.setSettingsStatusCode(-1);
			allWsSettings.setSettingsStatusMsg("Table columns has not been found.");
			return allWsSettings;
		}
		
		criteria = session.createCriteria(MqtTableSecurities.class);
		List<MqtTableSecurities> tableSecuritiesList = (List<MqtTableSecurities>)criteria.list();
		
		Collections.sort(tableSecuritiesList, new Comparator<MqtTableSecurities>() {
			public int compare(MqtTableSecurities o1, MqtTableSecurities o2) {
				return o1.getId()-o2.getId();
            }			
		});
		
		if (tableSecuritiesList != null) {
			List<MQSettingsSecurity> secuitiesNames = new ArrayList<MQSettingsSecurity>();
			Iterator<MqtTableSecurities> iter = tableSecuritiesList.iterator();
			while (iter.hasNext()) {
				MqtTableSecurities mqtTableSecurity= (MqtTableSecurities) iter.next();
				secuitiesNames.add(new MQSettingsSecurity(
						mqtTableSecurity.getSecurityName(),
						mqtTableSecurity.getSecurityShortname(),
						mqtTableSecurity.isIsWiped(),
						mqtTableSecurity.getMarket()));
            }
			allWsSettings.setSecuitiesNames(secuitiesNames);
		} else {
			logger.debug(methodName, " --- Table securities has not been found.");
			allWsSettings.setSettingsStatusCode(-1);
			allWsSettings.setSettingsStatusMsg("Table securities has not been found.");
			return allWsSettings;
		}			
		return allWsSettings;
	}
	
	
	private MQUserSettings translateUserSettingsToWS(MqtMobileSettings mobileSettings) {
		MQUserSettings wsSettings = new MQUserSettings();
		MQAppSettings appSettings = new MQAppSettings();
		appSettings.setSocketConnectionURL(mobileSettings.getMqtAppMobileSettings().getSocketConnectionUrl());
		appSettings.setQosName(mobileSettings.getMqtAppMobileSettings().getQosName());
		appSettings.setQuoteTopicName(mobileSettings.getMqtAppMobileSettings().getQuoteTopicName());
		appSettings.setPapTopicName(mobileSettings.getMqtAppMobileSettings().getPapTopicName());
		appSettings.setMarketInfoTopicName(mobileSettings.getMqtAppMobileSettings().getMarketInfoTopicName());
		wsSettings.setAppSettings(appSettings);
		
		MQPAPSettings papSettings = new MQPAPSettings();
	        String[] categoryNames = new String[mobileSettings.getMqtPapSettings().getMqtPapCategorySettingses().size()];
	        Iterator<MqtPapCategorySettings> iter11 = mobileSettings.getMqtPapSettings().getMqtPapCategorySettingses().iterator();
	        int i = 0;
	        while (iter11.hasNext()) {
	            MqtPapCategorySettings mqtPapCategorySettings = (MqtPapCategorySettings) iter11.next();
	            categoryNames[i++] = mqtPapCategorySettings.getMqtCategory().getName();
            }
			papSettings.setCategoryNames(categoryNames);
			papSettings.setCategorySortType((short)mobileSettings.getMqtPapSettings().getCategorySortType());
			papSettings.setMessageCount(mobileSettings.getMqtPapSettings().getMessageCount());
			
			String[] subCategoryNames = new String[mobileSettings.getMqtPapSettings().getMqtPapSubcategorySettingses().size()];
	        Iterator<MqtPapSubcategorySettings> iter12 = mobileSettings.getMqtPapSettings().getMqtPapSubcategorySettingses().iterator();
	        i = 0;
	        while (iter12.hasNext()) {
	        	MqtPapSubcategorySettings mqtPapSubcategorySettings = (MqtPapSubcategorySettings) iter12.next();
	        	subCategoryNames[i++] = mqtPapSubcategorySettings.getMqtSubcategory().getName();
            }			
			papSettings.setSubcategoryNames(subCategoryNames);
		wsSettings.setPapSettings(papSettings);
		
		MQTableSecDetailsSettingsDTO secDetailsSettings = new MQTableSecDetailsSettingsDTO();
		List<MQSettingsColumns> columnNames = new ArrayList<MQSettingsColumns>();

		TreeSet<MqtSecDetailsColumnsSettings> treeSet = new TreeSet<MqtSecDetailsColumnsSettings>(new Comparator<MqtSecDetailsColumnsSettings>() {
			public int compare(MqtSecDetailsColumnsSettings o1, MqtSecDetailsColumnsSettings o2) {
				return o1.getId()-o2.getId();
            }    		
    	});
    	treeSet.addAll(mobileSettings.getMqtSecDetailsColumnsSettingses());
    	Iterator<MqtSecDetailsColumnsSettings> iter2 = treeSet.iterator();
		while (iter2.hasNext()) {
	        MqtSecDetailsColumnsSettings mqtSecDetailsColumnsSettings = (MqtSecDetailsColumnsSettings) iter2.next();
	        MqtTableColumns columns = mqtSecDetailsColumnsSettings.getMqtTableColumns();
	        columnNames.add(new MQSettingsColumns(columns.getColumnName(), columns.getColumnShortname()));
        }		
		secDetailsSettings.setColumnNames(columnNames);
		wsSettings.setSecDetailsSettings(secDetailsSettings);
		
		MQTableTransListSettinngsDTO transListSettings = new MQTableTransListSettinngsDTO();
		columnNames = new ArrayList<MQSettingsColumns>();
		TreeSet<MqtTransListColumnsSettings> treeSet1 = new TreeSet<MqtTransListColumnsSettings>(new Comparator<MqtTransListColumnsSettings>() {
			public int compare(MqtTransListColumnsSettings o1, MqtTransListColumnsSettings o2) {
				return o1.getId()-o2.getId();
            }    		
    	});
    	treeSet1.addAll(mobileSettings.getMqtTransListColumnsSettingses());
    	Iterator<MqtTransListColumnsSettings> iter3 = treeSet1.iterator();
    	
		while (iter3.hasNext()) {
			MqtTransListColumnsSettings mqtTransListColumnsSettings = (MqtTransListColumnsSettings) iter3.next();
	        MqtTableColumns columns = mqtTransListColumnsSettings.getMqtTableColumns();
	        columnNames.add(new MQSettingsColumns(columns.getColumnName(), columns.getColumnShortname()));
        }		
		transListSettings.setColumnNames(columnNames);
		wsSettings.setTransListSettings(transListSettings);
		
		Map<String, MQTableSettingsDTO> tableSettings = new HashMap<String, MQTableSettingsDTO>();
		Iterator<MqtTableSettings> iter4 = mobileSettings.getMqtTableSettingses().iterator();
		while (iter4.hasNext()) {
	        MqtTableSettings mqtTableSettings = (MqtTableSettings) iter4.next();
	        MQTableSettingsDTO mqTableSettingsDTO = new MQTableSettingsDTO();	        
	        mqTableSettingsDTO.setColumnIsshortNames(mqtTableSettings.isColumnIsShortNames());
	        mqTableSettingsDTO.setSecurityIsshortNames(mqtTableSettings.isSecurityIsShortNames());
	        mqTableSettingsDTO.setOfferLineCount(mqtTableSettings.getOfferLineCount());
	        mqTableSettingsDTO.setTableName(mqtTableSettings.getTableName());
	        
	        List<MQSettingsColumns> tableColumnNames = new ArrayList<MQSettingsColumns>();
	        Iterator<MqtTableColumnsSettings> iter5 = mqtTableSettings.getMqtTableColumnsSettingses().iterator();
	        while (iter5.hasNext()) {
	            MqtTableColumnsSettings mqtTableColumnsSettings = (MqtTableColumnsSettings) iter5.next();
	            tableColumnNames.add(new MQSettingsColumns(
	            		mqtTableColumnsSettings.getMqtTableColumns().getColumnName(),
	            		mqtTableColumnsSettings.getMqtTableColumns().getColumnShortname()));
            }
			mqTableSettingsDTO.setColumnNames(tableColumnNames );	        
			
			List<MQSettingsSecurity> tableSecuitiesNames = new ArrayList<MQSettingsSecurity>();
	    	TreeSet<MqtTableSecuritiesSettings> treeSet2 = new TreeSet<MqtTableSecuritiesSettings>(new Comparator<MqtTableSecuritiesSettings>() {
				public int compare(MqtTableSecuritiesSettings o1, MqtTableSecuritiesSettings o2) {
					return o1.getId()-o2.getId();
	            }    		
	    	});
	    	treeSet2.addAll(mqtTableSettings.getMqtTableSecuritiesSettingses());

			Iterator<MqtTableSecuritiesSettings> iter6 = treeSet2.iterator();
			while (iter6.hasNext()) {
	            MqtTableSecuritiesSettings mqtTableSecuritiesSettings = (MqtTableSecuritiesSettings) iter6.next();
	            tableSecuitiesNames.add(new MQSettingsSecurity(
	            		mqtTableSecuritiesSettings.getMqtTableSecurities().getSecurityName(),
	            		mqtTableSecuritiesSettings.getMqtTableSecurities().getSecurityShortname(),
	            		mqtTableSecuritiesSettings.getMqtTableSecurities().isIsWiped(),
	            		mqtTableSecuritiesSettings.getMqtTableSecurities().getMarket()));
            }
			mqTableSettingsDTO.setSecuitiesNames(tableSecuitiesNames );
	        tableSettings.put(mqtTableSettings.getTableName(), mqTableSettingsDTO);
        }
		
		wsSettings.setTableSettings(tableSettings);
		return wsSettings;
	}
	
	public void releaseResources() {
		try {
			MQHibernateUtil.closeSession(ownership);
		} catch (Exception e) {
			logger.debug("releaseResources()", "Could not destroy database session, exception: " + e.getMessage());
		}
	}
}